#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
void print_str(const char* s) {
	int len = strlen(s), i = 0;
	while (i < len) putchar(s[i++]);
}
void wr(int x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) wr(x / 10);
	putchar(x % 10 + 48);
}

enum class Direction { UP, DOWN, LEFT, RIGHT };

class GraphicTablet {
protected:
	static const int max_pixel = 2010;
	static const bool multiple_case = true;
	char graphic[max_pixel][max_pixel];
public:
	GraphicTablet() { memset(graphic, 0, sizeof(graphic)); }
	void init() { memset(graphic, ' ', sizeof(graphic)); }
	//x : row y : col
	void paint(int grid_x, int grid_y, char s) { graphic[grid_x][grid_y] = s; }
	void print(int h, int w, int T) {
		if (multiple_case) print_str("Case "), wr(T), putchar(':'), putchar('\n');
		int i = 0, j = 0, lim = 0;
		for (i = 0; i < h; ++i) {
			lim = w - 1;
			while (graphic[i][lim] == ' ') --lim;//no trailing spaces
			for (j = 0; j <= lim; ++j) putchar(graphic[i][j]);
			putchar('\n');
		}
		if (multiple_case) putchar('\n');
	}
};

class Element {
protected:
	int width, height, center;//width : col height : row center : row
	Element* parent;//parent expression box
public:
	Element(Element* fa = nullptr) :parent(fa) { width = height = center = 0; }
	virtual ~Element() {}
	virtual void adjustSize() = 0;
	virtual void render(int grid_x, int grid_y, GraphicTablet* g) = 0;

	virtual bool moveDir(const Direction& id) = 0;
	virtual bool setLeftMost() = 0;
	virtual bool setRightMost() = 0;
	virtual bool moveHome() = 0;//using left most as sub-module
	virtual bool moveEnd() = 0;//using right most as sub-module

	virtual bool insert(Element* obj) = 0;
	virtual bool addRow() = 0;
	virtual bool addCol() = 0;

	inline int getHeight() { return height; }
	inline int getWidth() { return width; }
	inline int getUpperHeight() { return center - 1; }
	inline int getLowerHeight() { return height - center; }
	inline Element* getParent() { return parent; }
	inline void setParent(Element* fa) { parent = fa; }
};

class Character : public Element {
private:
	char val;
public:
	Character(Element* fa) : Element(fa), val(0) {}
	Character(char c, Element* fa) :Element(fa), val(c) {}
	virtual ~Character() {}
	virtual void adjustSize() {
		height = center = 1;
		width = (val == 0 ? 0 : (val == '-' ? 3 : 1));
	}
	//ignore operation
	virtual bool moveDir(const Direction& id) { return false; }
	virtual bool setLeftMost() { return false; }
	virtual bool setRightMost() { return false; }
	virtual bool moveHome() { return false; }
	virtual bool moveEnd() { return false; }

	virtual bool insert(Element* obj) { return false; }
	virtual bool addRow() { return false; }
	virtual bool addCol() { return false; }

	virtual void render(int grid_x, int grid_y, GraphicTablet* g) {
		switch (val) {
		case '\0':break;
		case '-':
			g->paint(grid_x, grid_y, ' ');
			g->paint(grid_x, grid_y + 2, ' ');
			g->paint(grid_x, grid_y + 1, val);
			break;
		default:
			g->paint(grid_x, grid_y, val);
			break;
		}
	}
};

class Sequence : public Element {
private:
	vector<Element*> elem_list;
	int cursor;
	enum class Sequence_Cursor { INSIDE, OUTSIDE } cursor_status;
	bool moveInsideCursor(const Direction& id) {
		if (cursor_status == Sequence_Cursor::INSIDE) {
			if (elem_list[cursor]->moveDir(id)) return true;
			else if (id == Direction::LEFT) { cursor_status = Sequence_Cursor::OUTSIDE; return true; }
			else if (id == Direction::RIGHT) { cursor_status = Sequence_Cursor::OUTSIDE; ++cursor; return true; }
			else return false;//ignore
		}
		else return false;
	}
	bool moveOutsideCursor(const Direction& id) {
		if (cursor_status == Sequence_Cursor::OUTSIDE) {
			if (id == Direction::LEFT && cursor > 0) {
				if (elem_list[cursor - 1]->setRightMost()) --cursor, cursor_status = Sequence_Cursor::INSIDE;
				else --cursor;
				return true;
			}
			else if (id == Direction::RIGHT && cursor < (int)elem_list.size()) {
				if (elem_list[cursor]->setLeftMost()) cursor_status = Sequence_Cursor::INSIDE;
				else ++cursor;
				return true;
			}
			else return false;
		}
		else return false;
	}
public:
	Sequence(Element* fa) : Element(fa) {
		elem_list.clear();
		cursor = 0;
		cursor_status = Sequence_Cursor::OUTSIDE;
	}
	virtual ~Sequence() { for (int i = 0; i < (int)elem_list.size(); ++i) delete elem_list[i]; }
	virtual void adjustSize() {
		width = 0;
		int upper_size = 0, lower_size = 0;
		for (int i = 0; i < (int)elem_list.size(); ++i) {
			elem_list[i]->adjustSize();
			width += elem_list[i]->getWidth();
			upper_size = max(upper_size, elem_list[i]->getUpperHeight());
			lower_size = max(lower_size, elem_list[i]->getLowerHeight());
		}
		height = upper_size + lower_size + 1;
		center = upper_size + 1;
	}

	virtual bool moveDir(const Direction& id) { return moveInsideCursor(id) || moveOutsideCursor(id); }
	virtual bool setLeftMost() {
		cursor = 0;
		cursor_status = Sequence_Cursor::OUTSIDE;
		return true;
	}
	virtual bool setRightMost() {
		cursor = (int)elem_list.size();
		cursor_status = Sequence_Cursor::OUTSIDE;
		return true;
	}
	virtual bool moveHome() {
		if (cursor_status == Sequence_Cursor::INSIDE) return elem_list[cursor]->moveHome();
		else return setLeftMost();
	}
	virtual bool moveEnd() {
		if (cursor_status == Sequence_Cursor::INSIDE) return elem_list[cursor]->moveEnd();
		else return setRightMost();
	}

	virtual bool insert(Element* obj) {
		if (cursor_status == Sequence_Cursor::INSIDE) return elem_list[cursor]->insert(obj);
		else {
			elem_list.insert(elem_list.begin() + cursor, obj);
			moveDir(Direction::RIGHT);
			obj->setParent(this);
			return true;
		}
	}
	virtual bool addRow() {
		if (cursor_status == Sequence_Cursor::INSIDE) return elem_list[cursor]->addRow();
		else return false;
	}
	virtual bool addCol() {
		if (cursor_status == Sequence_Cursor::INSIDE) return elem_list[cursor]->addCol();
		else return false;
	}

	virtual void render(int grid_x, int grid_y, GraphicTablet* g) {
		int center_x = grid_x + center - 1, start_y = grid_y;
		for (int i = 0; i < (int)elem_list.size(); ++i) {
			elem_list[i]->render(center_x - elem_list[i]->getUpperHeight(), start_y, g);
			start_y += elem_list[i]->getWidth();
		}
	}
};

class Fraction : public Element {
private:
	Element* numerator, * denominator;
	enum class Fraction_Cursor { NUMERATOR, DENOMINATOR } cursor;
	bool moveNumeratorCursor(const Direction& id) {
		if (cursor == Fraction_Cursor::NUMERATOR) {
			if (numerator->moveDir(id)) return true;
			else if (id == Direction::DOWN) { cursor = Fraction_Cursor::DENOMINATOR; return denominator->setLeftMost(); }
			else return false;
		}
		else return false;
	}
	bool moveDenominatorCursor(const Direction& id) {
		if (cursor == Fraction_Cursor::DENOMINATOR) {
			if (denominator->moveDir(id)) return true;
			else if (id == Direction::UP) { cursor = Fraction_Cursor::NUMERATOR; return numerator->setLeftMost(); }
			else return false;
		}
		else return false;
	}
public:
	Fraction(Element* fa) :Element(fa) {
		numerator = new Sequence(this), denominator = new Sequence(this);
		cursor = Fraction_Cursor::NUMERATOR;
	}
	virtual ~Fraction() { delete numerator, delete denominator; }

	virtual void adjustSize() {
		numerator->adjustSize(), denominator->adjustSize();
		width = max(numerator->getWidth(), denominator->getWidth()) + 2;
		height = numerator->getHeight() + denominator->getHeight() + 1;
		center = numerator->getHeight() + 1;
	}
	virtual bool moveDir(const Direction& id) { return moveNumeratorCursor(id) || moveDenominatorCursor(id); }
	virtual bool setLeftMost() {
		cursor = Fraction_Cursor::NUMERATOR;
		return numerator->setLeftMost();
	}
	virtual bool setRightMost() {
		cursor = Fraction_Cursor::NUMERATOR;
		return numerator->setRightMost();
	}
	virtual bool moveHome() {
		if (cursor == Fraction_Cursor::NUMERATOR) return numerator->moveHome();
		else return denominator->moveHome();
	}
	virtual bool moveEnd() {
		if (cursor == Fraction_Cursor::NUMERATOR) return numerator->moveEnd();
		else return denominator->moveEnd();
	}

	virtual bool insert(Element* obj) {
		if (cursor == Fraction_Cursor::NUMERATOR) return numerator->insert(obj);
		else return denominator->insert(obj);
	}
	virtual bool addRow() {
		if (cursor == Fraction_Cursor::NUMERATOR) return numerator->addRow();
		else return denominator->addRow();
	}
	virtual bool addCol() {
		if (cursor == Fraction_Cursor::NUMERATOR) return numerator->addCol();
		else return denominator->addCol();
	}

	virtual void render(int grid_x, int grid_y, GraphicTablet* g) {
		for (int i = 0; i < width; ++i)g->paint(grid_x + center - 1, grid_y + i, '-');
		numerator->render(grid_x, grid_y + ((width - numerator->getWidth()) >> 1), g);
		denominator->render(grid_x + center, grid_y + ((width - denominator->getWidth()) >> 1), g);
	}
};

class Matrix : public Element {
private:
	vector<vector<Element*> > elem_grid;
	int grid_row, grid_column;
	vector<int> upper_size_row, lower_size_row, size_column;
	int cursor_row, cursor_column;
public:
	Matrix(Element* fa) :Element(fa) {
		vector<Element*> tmp;
		tmp.push_back(new Sequence(this));//setting this as sub-box's father
		elem_grid.push_back(tmp);
		grid_row = grid_column = 1;
		cursor_row = cursor_column = 0;
	}
	virtual ~Matrix() {
		int i = 0, j = 0;
		for (i = 0; i < grid_row; ++i) for (j = 0; j < grid_column; ++j) delete elem_grid[i][j];
	}

	virtual void adjustSize() {
		upper_size_row.clear(), upper_size_row.resize(grid_row);
		lower_size_row.clear(), lower_size_row.resize(grid_row);
		size_column.clear(), size_column.resize(grid_column);


		for (int i = 0; i < grid_row; ++i) {
			for (int j = 0; j < grid_column; ++j) {
				elem_grid[i][j]->adjustSize();
				upper_size_row[i] = max(upper_size_row[i], elem_grid[i][j]->getUpperHeight());
				lower_size_row[i] = max(lower_size_row[i], elem_grid[i][j]->getLowerHeight());
				size_column[j] = max(size_column[j], elem_grid[i][j]->getWidth());
			}
		}
		height = grid_row - 1, width = grid_column + 1;
		for (int i = 0; i < grid_row; ++i) height += (upper_size_row[i] + lower_size_row[i] + 1);
		for (int j = 0; j < grid_column; ++j) width += size_column[j];

		if (grid_row & 1) {
			center = (grid_row >> 1) + 1 + upper_size_row[grid_row >> 1];
			for (int i = 0; i < (grid_row >> 1); ++i) center += (upper_size_row[i] + lower_size_row[i] + 1);
		}
		else {
			center = (grid_row >> 1);
			for (int i = 0; i < (grid_row >> 1); ++i) center += (upper_size_row[i] + lower_size_row[i] + 1);
		}
	}

	virtual bool moveDir(const Direction& id) {
		if (elem_grid[cursor_row][cursor_column]->moveDir(id)) return true;
		switch (id) {
		case Direction::UP:
			if (cursor_row > 0)return elem_grid[--cursor_row][cursor_column]->setLeftMost();
			break;
		case Direction::DOWN:
			if (cursor_row < grid_row - 1) return elem_grid[++cursor_row][cursor_column]->setLeftMost();
			break;
		case Direction::LEFT:
			if (cursor_column > 0)return elem_grid[cursor_row][--cursor_column]->setRightMost();
			break;
		case Direction::RIGHT:
			if (cursor_column < grid_column - 1) return elem_grid[cursor_row][++cursor_column]->setLeftMost();
			break;
		default:
			break;
		}
		return false;
	}
	virtual bool setLeftMost() {
		cursor_row = ((grid_row - 1) >> 1), cursor_column = 0;
		return elem_grid[cursor_row][cursor_column]->setLeftMost();
	}
	virtual bool setRightMost() {
		cursor_row = ((grid_row - 1) >> 1), cursor_column = grid_column - 1;
		return elem_grid[cursor_row][cursor_column]->setRightMost();
	}
	virtual bool moveHome() { return elem_grid[cursor_row][cursor_column]->moveHome(); }
	virtual bool moveEnd() { return elem_grid[cursor_row][cursor_column]->moveEnd(); }

	virtual bool insert(Element* obj) { return elem_grid[cursor_row][cursor_column]->insert(obj); }
	virtual bool addRow() {
		if (elem_grid[cursor_row][cursor_column]->addRow()) return true;
		++grid_row;
		vector<Element*> tmp;
		for (int j = 0; j < grid_column; ++j) tmp.push_back(new Sequence(this));
		elem_grid.insert(elem_grid.begin() + cursor_row, tmp);
		return true;
	}
	virtual bool addCol() {
		if (elem_grid[cursor_row][cursor_column]->addCol()) return true;
		++grid_column;
		vector<Element*> tmp;
		for (int i = 0; i < grid_row; ++i)
			elem_grid[i].insert(elem_grid[i].begin() + cursor_column, new Sequence(this));
		return true;
	}

	virtual void render(int grid_x, int grid_y, GraphicTablet* g) {
		int center_x = grid_x;
		for (int i = 0; i < grid_row; ++i) {
			center_x += upper_size_row[i];
			int center_y = grid_y + 1;
			g->paint(center_x, center_y - 1, '[');
			for (int j = 0; j < grid_column; ++j) {
				elem_grid[i][j]->render(center_x - elem_grid[i][j]->getUpperHeight(), center_y + ((size_column[j] - elem_grid[i][j]->getWidth()) >> 1), g);
				center_y += (size_column[j] + 1);
			}
			g->paint(center_x, center_y - 1, ']');
			center_x += lower_size_row[i] + 2;
		}
	}
};

class IO {
private:
	GraphicTablet graph;
	Sequence* root;
	int time_table;
public:
	IO() {
		graph.init();
		root = new Sequence(nullptr);
		time_table = 0;
	}

	void init() {
		delete root;
		graph.init();
		root = new Sequence(nullptr);
	}

	void print() {
		root->adjustSize();
		root->render(0, 0, &graph);
		graph.print(root->getHeight(), root->getWidth(), ++time_table);
	}

	bool input() {
		static char s[15] = { 0 };//disable non-zero warning
		if (scanf("%s", s) == EOF) return false; 

		if (!strcmp(s, "Matrix")) root->insert(new Matrix(nullptr));
		else if (!strcmp(s, "Fraction")) root->insert(new Fraction(nullptr));
		else if (!strcmp(s, "AddRow")) root->addRow();
		else if (!strcmp(s, "AddCol")) root->addCol();
		else if (!strcmp(s, "Home")) root->moveHome();
		else if (!strcmp(s, "End")) root->moveEnd();
		else if (!strcmp(s, "Left")) root->moveDir(Direction::LEFT);
		else if (!strcmp(s, "Right")) root->moveDir(Direction::RIGHT);
		else if (!strcmp(s, "Up")) root->moveDir(Direction::UP);
		else if (!strcmp(s, "Down")) root->moveDir(Direction::DOWN);
		else if (strlen(s) == 1) root->insert(new Character(s[0], nullptr));
		else if (!strcmp(s, "Done")) print(), init();
		else return false;//assert(0);
		
		return true;
	}
}solver;

int main() {
	while (solver.input());
}